package com.hy.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hy.appMedicine.dto.MedicineQueryDTO;
import com.hy.config.ImportDataListener;
import com.hy.config.ImportResult;
import com.hy.file.service.FileStorageService;
import com.hy.mapper.MedCommonCategoryMapper;
import com.hy.mapper.MedicineBasicInfoMapper;
import com.hy.mapper.PrescriptionCategoryMapper;
import com.hy.medicine.MedCommonCategory;
import com.hy.medicine.MedicineBasicInfo;
import com.hy.medicine.PrescriptionCategory;
import com.hy.medicine.dto.MedicineSearchDTO;
import com.hy.medicine.vo.MedicineBasicInfoVo;
import com.hy.medicine.vo.MedicineExportVO;
import com.hy.medicine.vo.MedicineImportTemplate;
import com.hy.service.MedicineBasicInfoService;
import com.hy.util.HttpStatus;
import com.hy.util.Result;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Lenovo
 * @description 针对表【medicine_basic_info(药品基本信息表)】的数据库操作Service实现
 * @createDate 2025-03-11 19:16:10
 */
@Service
public class MedicineBasicInfoServiceImpl extends ServiceImpl<MedicineBasicInfoMapper, MedicineBasicInfo>
        implements MedicineBasicInfoService {

    @Autowired
    private MedicineBasicInfoMapper medicineBasicInfoMapper;

    @Autowired
    private MedCommonCategoryMapper medCommonCategoryMapper;

    @Autowired
    private PrescriptionCategoryMapper prescriptionCategoryMapper;

    @Value("${excel.batch-size:1000}")
    private int batchSize;

    /**
     * 验证分类ID是否存在
     */
    private void validateCategoryIds(MedicineImportTemplate template, List<String> errors) {
        // 验证通用分类ID
        if (medCommonCategoryMapper.selectById(template.getCommonCategoryId()) == null) {
            errors.add(String.format("通用分类ID[%s]不存在", template.getCommonCategoryId()));
        }

        // 验证处方分类ID
        if (prescriptionCategoryMapper.selectById(template.getPrescriptionCategoryId()) == null) {
            errors.add(String.format("处方分类ID[%s]不存在", template.getPrescriptionCategoryId()));
        }
    }

    /**
     * 下载导入模板
     */
    @Override
    public void downloadTemplate(HttpServletResponse response) throws IOException {
        try {
            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("药品导入模板", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            // 创建工作簿
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();

            // 写入数据页
            WriteSheet dataSheet = EasyExcel.writerSheet(0, "药品信息")
                    .head(MedicineImportTemplate.class)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .build();

            // 创建示例数据
            List<MedicineImportTemplate> templateList = new ArrayList<>();
            templateList.add(createExampleData());
            excelWriter.write(templateList, dataSheet);

            // 写入说明页
            WriteSheet noteSheet = EasyExcel.writerSheet(1, "填写说明")
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .build();

            // 创建说明内容
            List<List<String>> noteList = new ArrayList<>();
            // 添加字段说明
            noteList.add(Arrays.asList("字段说明："));
            noteList.add(Arrays.asList("字段名", "说明", "是否必填", "示例"));
            noteList.add(Arrays.asList("药品名称", "药品通用名称", "是", "阿莫西林胶囊"));
            noteList.add(Arrays.asList("批准文号", "药品批准文号", "是", "国药准字H12345678"));
            noteList.add(Arrays.asList("规格", "药品规格", "是", "0.25g*24粒/盒"));
            noteList.add(Arrays.asList("剂型", "药品剂型", "是", "胶囊剂"));
            noteList.add(Arrays.asList("生产厂家", "生产企业名称", "是", "示例制药有限公司"));
            noteList.add(Arrays.asList("保质期(月)", "药品保质期，单位：月", "是", "36"));
            noteList.add(Arrays.asList("储存条件", "药品储存要求", "是", "密封，常温保存"));
            noteList.add(Arrays.asList("单价(元)", "药品单价", "是", "29.80"));
            // noteList.add(Arrays.asList("库存数量", "初始库存数量", "是", "1000"));
            noteList.add(Arrays.asList("通用分类ID", "药品分类编码", "是", "cold"));
            noteList.add(Arrays.asList("处方分类ID", "处方类型编码", "是", "otc"));

            noteList.add(Arrays.asList("")); // 空行

            // 从数据库获取实际的分类列表
            List<MedCommonCategory> commonCategories = medCommonCategoryMapper.selectList(null);
            List<PrescriptionCategory> prescriptionCategories = prescriptionCategoryMapper.selectList(null);

            // 添加分类对照表
            noteList.add(Arrays.asList("通用分类ID对照表："));
            noteList.add(Arrays.asList("ID", "名称"));
            for (MedCommonCategory category : commonCategories) {
                noteList.add(Arrays.asList(category.getId(), category.getName()));
            }

            noteList.add(Arrays.asList("")); // 空行
            noteList.add(Arrays.asList("处方分类ID对照表："));
            noteList.add(Arrays.asList("ID", "名称"));
            for (PrescriptionCategory category : prescriptionCategories) {
                noteList.add(Arrays.asList(category.getId(), category.getName()));
            }

            excelWriter.write(noteList, noteSheet);

            // 关闭写入器
            excelWriter.finish();

        } catch (Exception e) {
            log.error("下载模板失败", e);
            throw e;
        }
    }

    /**
     * 导入药品信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Serializable> importMedicine(MultipartFile file) {
        ImportResult importResult = new ImportResult();

        try {
            // 创建自定义监听器，传入验证方法
            ImportDataListener listener = new ImportDataListener(
                    medicineBasicInfoMapper,
                    importResult,
                    batchSize,
                    this::validateCategoryIds  // 传入验证方法
            );

            EasyExcel.read(file.getInputStream(), MedicineImportTemplate.class, listener)
                    .sheet()
                    .doRead();

            String msg = String.format("导入完成，成功：%d，失败：%d",
                    importResult.getSuccessCount(), importResult.getFailCount());

            Result<Serializable> result = importResult.getFailCount() > 0 ?
                    new Result<Serializable>(HttpStatus.WARN, msg) :
                    new Result<Serializable>(HttpStatus.SUCCESS, msg);

            result.put("successCount", importResult.getSuccessCount());
            result.put("failCount", importResult.getFailCount());
            result.put("errorMessages", importResult.getErrorMessages());

            return result;
        } catch (FileNotFoundException e) {
            log.error("文件未找到", e);
            return new Result<Serializable>(HttpStatus.ERROR, "导入失败: 文件未找到");
        } catch (IOException e) {
            log.error("文件读取异常", e);
            return new Result<Serializable>(HttpStatus.ERROR, "导入失败: 文件读取异常");
        } catch (DataIntegrityViolationException e) {
            log.error("数据完整性错误", e);
            return new Result<Serializable>(HttpStatus.ERROR, "导入失败: 数据完整性错误，请检查数据");
        } catch (Exception e) {
            log.error("导入失败", e);
            return new Result<Serializable>(HttpStatus.ERROR, "导入失败: " + e.getMessage());
        }
    }

    /**
     * 创建示例数据
     */
    private MedicineImportTemplate createExampleData() {
        MedicineImportTemplate template = new MedicineImportTemplate();
        template.setMedicineName("阿莫西林胶囊");
        template.setApprovalNumber("国药准字H12345678");
        template.setSpecification("0.25g*24粒/盒");
        template.setDosageForm("胶囊剂");
        template.setManufacturer("示例制药有限公司");
        template.setShelfLife(36);
        template.setStorageCondition("密封，常温保存");
        template.setPrice(new BigDecimal("29.80"));
        template.setMinStock(1000);
        template.setCommonCategoryId("cold");
        template.setPrescriptionCategoryId("otc");
        return template;
    }

    /**
     * 导出药品信息
     */
    @Override
    public void exportMedicine(MedicineBasicInfoVo vo, HttpServletResponse response) throws IOException {
        try {
            // 设置响应头
            setExportResponseHeaders(response);

            // 查询数据
            List<MedicineBasicInfo> list = queryExportData(vo);
            if (CollectionUtils.isEmpty(list)) {
                throw new RuntimeException("没有找到符合条件的数据");
            }

            // 转换为导出VO
            List<MedicineExportVO> exportList = convertToExportVO(list);

            // 写入Excel
            EasyExcel.write(response.getOutputStream(), MedicineExportVO.class)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自适应列宽
                    .sheet("药品信息")
                    .doWrite(exportList);

        } catch (Exception e) {
            log.error("导出Excel失败", e);
            throw e;
        }
    }


    /**
     * 设置导出响应头
     */
    private void setExportResponseHeaders(HttpServletResponse response) throws UnsupportedEncodingException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("药品信息", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    }

    /**
     * 查询导出数据
     */
    private List<MedicineBasicInfo> queryExportData(MedicineBasicInfoVo vo) {
        return this.lambdaQuery()
                .like(StringUtils.isNotBlank(vo.getMedicineName()),
                        MedicineBasicInfo::getMedicineName, vo.getMedicineName())
                .like(StringUtils.isNotBlank(vo.getManufacturer()),
                        MedicineBasicInfo::getManufacturer, vo.getManufacturer())
                .eq(vo.getCommonCategoryId() != null,
                        MedicineBasicInfo::getCommonCategoryId, vo.getCommonCategoryId())
                .orderByDesc(MedicineBasicInfo::getMedicineId)
                .list();
    }

    /**
     * 转换为导出VO
     */
    private List<MedicineExportVO> convertToExportVO(List<MedicineBasicInfo> list) {
        return list.stream()
                .map(medicine -> {
                    MedicineExportVO exportVO = new MedicineExportVO();
                    BeanUtils.copyProperties(medicine, exportVO);
                    return exportVO;
                })
                .collect(Collectors.toList());
    }


    /**
     * 根据条件查询药品信息
     *
     * @param medicineBasicInfoVo
     * @return
     */
    @Override
    public Result<Serializable> getMedicineInfo(MedicineBasicInfoVo medicineBasicInfoVo) {
        PageHelper.startPage(medicineBasicInfoVo.getPageNum(), medicineBasicInfoVo.getPageSize());
        List<MedicineBasicInfo> medicineBasicInfos = medicineBasicInfoMapper.getMedicineInfo(medicineBasicInfoVo);
        PageInfo<MedicineBasicInfo> medicineBasicInfoPageInfo = new PageInfo<>(medicineBasicInfos);
        return Result.success(medicineBasicInfoPageInfo);
    }

    /**
     * 根据条件搜索药品列表
     *
     * @param dto 包含搜索条件的MedicineSearchDTO对象
     * @return 返回搜索结果或操作结果
     */
    @Override
    public Result searchMedicineList(MedicineSearchDTO dto) {
        try {
            // 初始化分页对象，设置当前页码和每页大小
            Page<MedicineBasicInfo> page = new Page<>(dto.getPageNum(), dto.getPageSize());
            // 创建LambdaQueryWrapper对象用于构建查询条件
            LambdaQueryWrapper<MedicineBasicInfo> wrapper = new LambdaQueryWrapper<>();

            // 添加查询条件：如果药品名称不为空，则按药品名称模糊查询
            wrapper.like(StrUtil.isNotBlank(dto.getMedicineName()),
                            MedicineBasicInfo::getMedicineName, dto.getMedicineName())
                    // 添加查询条件：如果生产商不为空，则按生产商模糊查询
                    .like(StrUtil.isNotBlank(dto.getManufacturer()),
                            MedicineBasicInfo::getManufacturer, dto.getManufacturer())
                    // 添加查询条件：如果通用类别ID不为空，则按通用类别ID精确查询
                    .eq(StrUtil.isNotBlank(dto.getCommonCategoryId()),
                            MedicineBasicInfo::getCommonCategoryId, dto.getCommonCategoryId())
                    // 添加查询条件：如果处方类别ID不为空，则按处方类别ID精确查询
                    .eq(StrUtil.isNotBlank(dto.getPrescriptionCategoryId()),
                            MedicineBasicInfo::getPrescriptionCategoryId, dto.getPrescriptionCategoryId())
                    // 添加查询条件：如果批准文号不为空，则按批准文号精确查询
                    .eq(StrUtil.isNotBlank(dto.getApprovalNumber()),
                            MedicineBasicInfo::getApprovalNumber, dto.getApprovalNumber());

            // 执行分页查询
            IPage<MedicineBasicInfo> result = this.page(page, wrapper);
            // 返回查询成功的结果
            return Result.success(result);
        } catch (Exception e) {
            // 记录错误日志
            log.error("搜索药品列表失败", e);
            // 返回错误结果
            return Result.error("搜索药品列表失败");
        }
    }

    /**
     * 添加新的药品信息
     *
     * @param medicineBasicInfo 包含需要添加的药品信息的对象
     * @return 返回操作结果，成功或失败
     */
    @Override
    public Result addMedicine(MedicineBasicInfo medicineBasicInfo) {
        try {
            // 参数校验
            if (StringUtils.isBlank(medicineBasicInfo.getMedicineName())) {
                return Result.error("药品名称不能为空");
            }

            // 检查药品名称是否重复
            LambdaQueryWrapper<MedicineBasicInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(MedicineBasicInfo::getMedicineName, medicineBasicInfo.getMedicineName())
                    .eq(MedicineBasicInfo::getDeleted, 1);
            if (medicineBasicInfoMapper.selectCount(queryWrapper) > 0) {
                return Result.error("药品名称已存在");
            }

            // 验证分类是否存在
            if (!validateCategories(medicineBasicInfo)) {
                return Result.error("所选分类不存在");
            }

            // 设置初始值
            medicineBasicInfo.setDeleted(1);
            medicineBasicInfo.setSalesVolume(medicineBasicInfo.getSalesVolume() != null ?
                    medicineBasicInfo.getSalesVolume() : 0);

            // 保存药品信息
            int result = medicineBasicInfoMapper.insert(medicineBasicInfo);
            return result > 0 ? Result.success("添加成功") : Result.error("添加失败");
        } catch (Exception e) {
            log.error("添加药品失败:", e);
            return Result.error("系统错误");
        }
    }


    // 验证分类是否存在
    private boolean validateCategories(MedicineBasicInfo medicine) {
        if (StringUtils.isNotBlank(medicine.getCommonCategoryId())) {
            MedCommonCategory commonCategory = medCommonCategoryMapper.selectById(medicine.getCommonCategoryId());
            if (commonCategory == null) {
                return false;
            }
        }

        if (StringUtils.isNotBlank(medicine.getPrescriptionCategoryId())) {
            PrescriptionCategory prescriptionCategory = prescriptionCategoryMapper.selectById(
                    medicine.getPrescriptionCategoryId()
            );
            if (prescriptionCategory == null || prescriptionCategory.getStatus() != 1) {
                return false;
            }
        }

        return true;
    }

    /**
     * 更新药品信息
     *
     * @param medicineBasicInfo 包含需要更新的药品信息的对象
     * @return 返回操作结果，成功或失败
     */
    @Override
    public Result updateMedicine(MedicineBasicInfo medicineBasicInfo) {
        try {
            // 参数校验：检查药品ID是否为空
            if (medicineBasicInfo.getMedicineId() == null) {
                return Result.error("药品ID不能为空");
            }

            // 检查药品是否存在且未被删除
            MedicineBasicInfo existMedicine = medicineBasicInfoMapper.selectById(medicineBasicInfo.getMedicineId());
            if (existMedicine == null || existMedicine.getDeleted() == 0) {
                return Result.error("药品不存在");
            }

            // 检查药品名称是否重复（排除自身）
            if (!existMedicine.getMedicineName().equals(medicineBasicInfo.getMedicineName())) {
                LambdaQueryWrapper<MedicineBasicInfo> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(MedicineBasicInfo::getMedicineName, medicineBasicInfo.getMedicineName())
                        .eq(MedicineBasicInfo::getDeleted, 1);
                if (medicineBasicInfoMapper.selectCount(queryWrapper) > 0) {
                    return Result.error("药品名称已存在");
                }
            }

            // 更新药品信息到数据库
            int result = medicineBasicInfoMapper.updateById(medicineBasicInfo);
            if (result > 0) {
                return Result.success("更新成功");
            }
            return Result.error("更新失败");
        } catch (Exception e) {
            // 记录更新药品时发生的异常
            log.error("更新药品失败:", e);
            // 返回系统错误信息
            return Result.error("系统错误");
        }
    }


    /**
     * 逻辑删除药品信息
     *
     * @param medicineBasicInfo 需要删除的药品ID
     * @return 返回操作结果，成功或失败
     */
    @Override
    public Result deleteMedicine(MedicineBasicInfo medicineBasicInfo) {
        try {
            // 参数校验：检查药品ID是否为空
            if (medicineBasicInfo.getMedicineId() == null) {
                return Result.error("药品ID不能为空");
            }

            // 检查药品是否存在且未被逻辑删除
            MedicineBasicInfo medicine = medicineBasicInfoMapper.selectById(medicineBasicInfo.getMedicineId());
            if (medicine == null || medicine.getDeleted() == 0) {
                return Result.error("药品不存在");
            }

            // 设置药品的删除标志为已删除
            medicine.setDeleted(0);
            // 执行更新操作
            int result = medicineBasicInfoMapper.updateById(medicine);
            if (result > 0) {
                return Result.success("删除成功");
            }
            return Result.error("删除失败");
        } catch (Exception e) {
            // 记录删除药品时发生的异常
            log.error("删除药品失败:", e);
            // 返回系统错误信息
            return Result.error("系统错误");
        }
    }



    /**
     * 获取药品详情
     *
     * @param medicineId 需要查询的药品ID
     * @return 返回包含药品详情的结果对象，成功或失败
     */
    @Override
    public Result getMedicineDetail(Integer medicineId) {
        try {
            if (medicineId == null) {
                return Result.error("药品ID不能为空");
            }

            MedicineBasicInfo medicine = medicineBasicInfoMapper.selectById(medicineId);
            if (medicine == null || medicine.getDeleted() == 0) {
                return Result.error("药品不存在");
            }

            // 补充分类名称
            fillCategoryNames(medicine);

            return Result.success(medicine);
        } catch (Exception e) {
            log.error("获取药品详情失败:", e);
            return Result.error("系统错误");
        }
    }
    // 填充分类名称
    private void fillCategoryNames(MedicineBasicInfo medicine) {
        if (StringUtils.isNotBlank(medicine.getCommonCategoryId())) {
            MedCommonCategory commonCategory = medCommonCategoryMapper.selectById(medicine.getCommonCategoryId());
            if (commonCategory != null) {
                medicine.setCommonCategoryName(commonCategory.getName());
            }
        }

        if (StringUtils.isNotBlank(medicine.getPrescriptionCategoryId())) {
            PrescriptionCategory prescriptionCategory = prescriptionCategoryMapper.selectById(
                    medicine.getPrescriptionCategoryId()
            );
            if (prescriptionCategory != null && prescriptionCategory.getStatus() == 1) {
                medicine.setPrescriptionCategoryName(prescriptionCategory.getName());
            }
        }
    }


    @Autowired
    private FileStorageService fileStorageService;
    /**
     * 上传图片
     * @param file
     * @return
     */
    @Override
    public String updatefile(MultipartFile file) throws Exception {
        if(file==null || file.getSize()<0){
            return "";
        }
        String s = fileStorageService.uploadImageFile(file.getOriginalFilename(), file.getInputStream());
        return s;

    }

    @Override
    public Result searchMedicineSockList(MedicineQueryDTO queryDTO) {
        LambdaQueryWrapper<MedicineBasicInfo> queryWrapper = new LambdaQueryWrapper<>();

        // 设置查询条件
        if (StringUtils.isNotBlank(queryDTO.getMedicineName())) {
            queryWrapper.like(MedicineBasicInfo::getMedicineName, queryDTO.getMedicineName());
        }

        // 按药品名称排序
        queryWrapper.orderByAsc(MedicineBasicInfo::getMedicineName);

        // 执行分页查询
        Page<MedicineBasicInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        return Result.success(medicineBasicInfoMapper.selectPage(page, queryWrapper));
    }
}




